home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / frasrc19.zip / LOADFILE.C < prev    next >
C/C++ Source or Header  |  1995-03-04  |  39KB  |  1,290 lines

  1. /*
  2.     loadfile.c - load an existing fractal image, control level
  3. */
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #ifndef XFRACT
  9. #include <dos.h>
  10. #endif
  11. #include <time.h>
  12. #include <errno.h>
  13. #ifdef XFRACT
  14. #include <unistd.h>
  15. #endif
  16. #include "fractint.h"
  17. #include "fractype.h"
  18. #include "helpdefs.h"
  19. #include "targa_lc.h"
  20. #include "prototyp.h"
  21.  
  22. /* routines in this module    */
  23.  
  24. static int  find_fractal_info(char *,struct fractal_info *,struct ext_blk_2 *,
  25.             struct ext_blk_3 *,struct ext_blk_4 *,struct ext_blk_5 *);
  26. static void load_ext_blk(char far *loadptr,int loadlen);
  27. static void skip_ext_blk(int *,int *);
  28. static void backwardscompat(struct fractal_info *info);
  29.  
  30. int filetype;
  31. int loaded3d;
  32. static FILE *fp;
  33. int fileydots, filexdots, filecolors;
  34. float fileaspectratio;
  35. short skipxdots,skipydots;    /* for decoder, when reducing image */
  36.  
  37. #ifdef XFRACT
  38. int decode_fractal_info();
  39. #endif
  40.  
  41. int read_overlay()    /* read overlay/3D files, if reqr'd */
  42. {
  43.    struct fractal_info read_info;
  44.    char oldfloatflag;
  45.    char msg[110];
  46.    struct ext_blk_2 blk_2_info;
  47.    struct ext_blk_3 blk_3_info;
  48.    struct ext_blk_4 blk_4_info;
  49.    struct ext_blk_5 blk_5_info;
  50.  
  51.    showfile = 1;        /* for any abort exit, pretend done */
  52.    initmode = -1;        /* no viewing mode set yet */
  53.    oldfloatflag = usr_floatflag;
  54.    loaded3d = 0;
  55.  
  56.    if(strchr(readname,'.') == NULL)
  57.       strcat(readname,".gif");
  58.  
  59.    if(find_fractal_info(readname,&read_info,&blk_2_info,&blk_3_info,
  60.                         &blk_4_info,&blk_5_info)) {
  61.       /* didn't find a useable file */
  62.       sprintf(msg,"Sorry, %s isn't a file I can decode.",readname);
  63.       stopmsg(0,msg);
  64.       return(-1);
  65.       }
  66.  
  67.    maxit    = read_info.iterationsold;
  68.    fractype    = read_info.fractal_type;
  69.    if (fractype < 0 || fractype >= num_fractal_types) {
  70.       sprintf(msg,"Warning: %s has a bad fractal type; using 0",readname);
  71.       fractype = 0;
  72.    }
  73.    curfractalspecific = &fractalspecific[fractype];
  74.    xxmin    = read_info.xmin;
  75.    xxmax    = read_info.xmax;
  76.    yymin    = read_info.ymin;
  77.    yymax    = read_info.ymax;
  78.    param[0]    = read_info.creal;
  79.    param[1]    = read_info.cimag;
  80.    save_release = 1100; /* unless we find out better later on */
  81.  
  82.    invert = 0;
  83.    if(read_info.version > 0) {
  84.       param[2]        = read_info.parm3;
  85.       roundfloatd(¶m[2]);
  86.       param[3]        = read_info.parm4;
  87.       roundfloatd(¶m[3]);
  88.       potparam[0]   = read_info.potential[0];
  89.       potparam[1]   = read_info.potential[1];
  90.       potparam[2]   = read_info.potential[2];
  91.       potflag        = (potparam[0] != 0.0);
  92.       rflag        = read_info.rflag;
  93.       rseed        = read_info.rseed;
  94.       inside        = read_info.inside;
  95.       LogFlag        = read_info.logmap;
  96.       inversion[0]  = read_info.invert[0];
  97.       inversion[1]  = read_info.invert[1];
  98.       inversion[2]  = read_info.invert[2];
  99.       if (inversion[0] != 0.0)
  100.      invert = 3;
  101.       decomp[0]     = read_info.decomp[0];
  102.       decomp[1]     = read_info.decomp[1];
  103.       usr_biomorph  = read_info.biomorph;
  104.       forcesymmetry = read_info.symmetry;
  105.       }
  106.  
  107.    if(read_info.version > 1) {
  108.       save_release  = 1200;
  109.       if (!display3d
  110.     && (read_info.version <= 4 || read_info.flag3d > 0
  111.         || (curfractalspecific->flags&PARMS3D) )) {
  112.      int i;
  113.      for (i = 0; i < 16; i++)
  114.         init3d[i] = read_info.init3d[i];
  115.      previewfactor     = read_info.previewfactor;
  116.      xtrans      = read_info.xtrans;
  117.      ytrans      = read_info.ytrans;
  118.      red_crop_left     = read_info.red_crop_left;
  119.      red_crop_right  = read_info.red_crop_right;
  120.      blue_crop_left  = read_info.blue_crop_left;
  121.      blue_crop_right = read_info.blue_crop_right;
  122.      red_bright     = read_info.red_bright;
  123.      blue_bright     = read_info.blue_bright;
  124.      xadjust     = read_info.xadjust;
  125.      eyeseparation     = read_info.eyeseparation;
  126.      glassestype     = read_info.glassestype;
  127.      }
  128.       }
  129.  
  130.    if(read_info.version > 2) {
  131.       save_release = 1300;
  132.       outside       = read_info.outside;
  133.       }
  134.  
  135.    calc_status = 0;      /* defaults if version < 4 */
  136.    xx3rd = xxmin;
  137.    yy3rd = yymin;
  138.    usr_distest = 0;
  139.    calctime = 0;
  140.    if(read_info.version > 3) {
  141.       save_release = 1400;
  142.       xx3rd      = read_info.x3rd;
  143.       yy3rd      = read_info.y3rd;
  144.       calc_status = read_info.calc_status;
  145.       usr_stdcalcmode = read_info.stdcalcmode;
  146.       three_pass = 0;
  147.       if(usr_stdcalcmode == 127)
  148.       {
  149.          three_pass = 1;
  150.          usr_stdcalcmode = '3';
  151.       }
  152.       usr_distest     = read_info.distest;
  153.       usr_floatflag   = (char)read_info.floatflag;
  154.       bailout      = read_info.bailoutold;
  155.       calctime      = read_info.calctime;
  156.       trigndx[0]  = read_info.trigndx[0];
  157.       trigndx[1]  = read_info.trigndx[1];
  158.       trigndx[2]  = read_info.trigndx[2];
  159.       trigndx[3]  = read_info.trigndx[3];
  160.       finattract  = read_info.finattract;
  161.       initorbit.x = read_info.initorbit[0];
  162.       initorbit.y = read_info.initorbit[1];
  163.       useinitorbit = read_info.useinitorbit;
  164.       usr_periodicitycheck = read_info.periodicity;
  165.       }
  166.  
  167.    pot16bit = 0;
  168.    save_system = 0;
  169.    if(read_info.version > 4) {
  170.       pot16bit       = read_info.pot16bit;
  171.       if (pot16bit)
  172.      filexdots >>= 1;
  173.       fileaspectratio = read_info.faspectratio;
  174.       if (fileaspectratio < 0.01)    /* fix files produced in early v14.1 */
  175.      fileaspectratio = screenaspect;
  176.       save_system  = read_info.system;
  177.       save_release = read_info.release; /* from fmt 5 on we know real number */
  178.       if (read_info.version == 5    /* except a few early fmt 5 cases: */
  179.       && (save_release <= 0 || save_release >= 2000)) {
  180.      save_release = 1410;
  181.      save_system = 0;
  182.      }
  183.       if (!display3d && read_info.flag3d > 0) {
  184.      loaded3d    = 1;
  185.      Ambient    = read_info.ambient;
  186.      RANDOMIZE    = read_info.randomize;
  187.      haze        = read_info.haze;
  188.      transparent[0] = read_info.transparent[0];
  189.      transparent[1] = read_info.transparent[1];
  190.      }
  191.       }
  192.  
  193.    rotate_lo = 1; rotate_hi = 255;
  194.    distestwidth = 71;
  195.    if(read_info.version > 5) {
  196.       rotate_lo     = read_info.rotate_lo;
  197.       rotate_hi     = read_info.rotate_hi;
  198.       distestwidth    = read_info.distestwidth;
  199.       }
  200.  
  201.    if(read_info.version > 6) {
  202.       param[2]        = read_info.dparm3;
  203.       param[3]        = read_info.dparm4;
  204.       }
  205.  
  206.    if(read_info.version > 7) {
  207.       fillcolor        = read_info.fillcolor;
  208.       }
  209.  
  210.    if(read_info.version > 8) {
  211.    mxmaxfp   =  read_info.mxmaxfp        ;
  212.    mxminfp   =  read_info.mxminfp        ;
  213.    mymaxfp   =  read_info.mymaxfp        ;
  214.    myminfp   =  read_info.myminfp        ;
  215.    zdots     =  read_info.zdots          ;        
  216.    originfp  =  read_info.originfp       ;
  217.    depthfp   =  read_info.depthfp        ;    
  218.    heightfp  =  read_info.heightfp       ;
  219.    widthfp   =  read_info.widthfp        ;    
  220.    distfp    =  read_info.distfp         ;    
  221.    eyesfp    =  read_info.eyesfp         ;    
  222.    neworbittype = read_info.orbittype    ;
  223.    juli3Dmode   = read_info.juli3Dmode   ;
  224.    maxfn    =   (char)read_info.maxfn          ;
  225.    major_method = (enum Major)read_info.inversejulia >> 8;
  226.    minor_method = (enum Minor)read_info.inversejulia & 255;
  227.    param[4] = read_info.dparm5;
  228.    param[5] = read_info.dparm6;
  229.    param[6] = read_info.dparm7;
  230.    param[7] = read_info.dparm8;
  231.    param[8] = read_info.dparm9;
  232.    param[9] = read_info.dparm10;
  233.       }
  234.  
  235.    if(read_info.version < 4) { /* pre-version 14.0? */
  236.       backwardscompat(&read_info); /* translate obsolete types */
  237.       if(LogFlag)
  238.      LogFlag = 2;
  239.       usr_floatflag = (char)((curfractalspecific->isinteger) ? 0 : 1);
  240.       }
  241.  
  242.    if (read_info.version < 5) { /* pre-version 15.0? */
  243.       if (LogFlag == 2) /* logmap=old changed again in format 5! */
  244.      LogFlag = -1;
  245.       if (decomp[0] > 0 && decomp[1] > 0)
  246.      bailout = decomp[1];
  247.       }
  248.    if(potflag) /* in version 15.x and 16.x logmap didn't work with pot */
  249.       if(read_info.version == 6 || read_info.version == 7)
  250.          LogFlag = 0;
  251.    set_trig_pointers(-1);
  252.  
  253.    if(read_info.version < 9) { /* pre-version 18.0? */
  254.       /* forcesymmetry==1000 means we want to force symmetry but don't
  255.          know which symmetry yet, will find out in setsymmetry() */
  256.       if(outside==REAL || outside==IMAG || outside==MULT || outside==SUM
  257.         || outside==ATAN)
  258.          if(forcesymmetry == 999)
  259.             forcesymmetry = 1000;
  260.       }
  261.    if(save_release < 1725) { /* pre-version 17.25 */
  262.       set_if_old_bif(); /* translate bifurcation types */
  263.       functionpreloaded = 1;
  264.    }
  265.  
  266.    if(save_release > 1822)
  267.    { /* post-version 18.22 */
  268.       bailout     = read_info.bailout; /* use long bailout */
  269.       bailoutest = (enum bailouts)read_info.bailoutest;
  270.    }
  271.    else
  272.       bailoutest = Mod;
  273.    setbailoutformula(bailoutest);
  274.  
  275.    if(save_release > 1823)
  276.      /* post-version 18.23 */
  277.       maxit = read_info.iterations; /* use long maxit */
  278.  
  279.    if (save_release > 1827) /* post-version 18.27 */
  280.       old_demm_colors = read_info.old_demm_colors;
  281.  
  282.    backwards_v18();
  283.    backwards_v19();
  284.  
  285.    if (display3d)            /* PB - a klooge till the meaning of */
  286.       usr_floatflag = oldfloatflag; /*    floatflag in line3d is clarified */
  287.  
  288.    if (overlay3d) {
  289.       initmode = adapter;       /* use previous adapter mode for overlays */
  290.       if (filexdots > xdots || fileydots > ydots) {
  291.      static FCODE msg[]={"Can't overlay with a larger image"};
  292.      stopmsg(0,msg);
  293.      initmode = -1;
  294.      return(-1);
  295.      }
  296.       }
  297.    else {
  298.       int olddisplay3d,i;
  299.       char oldfloatflag;
  300.       olddisplay3d = display3d;
  301.       oldfloatflag = floatflag;
  302.       display3d = loaded3d;      /* for <tab> display during next */
  303.       floatflag = usr_floatflag; /* ditto */
  304.       i = get_video_mode(&read_info,&blk_3_info);
  305.       display3d = olddisplay3d;
  306.       floatflag = oldfloatflag;
  307.       if (i) {
  308.      initmode = -1;
  309.      return(-1);
  310.      }
  311.       }
  312.  
  313.    if (display3d) {
  314.       calc_status = 0;
  315.       fractype = PLASMA;
  316.       curfractalspecific = &fractalspecific[PLASMA];
  317.       param[0] = 0;
  318.       if (!initbatch)
  319.      if (get_3d_params() < 0) {
  320.         initmode = -1;
  321.         return(-1);
  322.         }
  323.       }
  324.  
  325.    if (resume_info != NULL) { /* free the prior area if there is one */
  326.       farmemfree(resume_info);
  327.       resume_info = NULL;
  328.       }
  329.  
  330.    if(blk_2_info.got_data == 1)
  331.       {
  332.       resume_info = blk_2_info.resume_data;
  333.       resume_len = blk_2_info.length;
  334.       }
  335.  
  336.    if(blk_3_info.got_data == 1)
  337.       {
  338.       char *nameptr;
  339.       switch (read_info.fractal_type) {
  340.          case LSYSTEM:
  341.         nameptr = LName;
  342.         break;
  343.          case IFS:
  344.          case IFS3D:
  345.         nameptr = IFSName;
  346.         break;
  347.          default:
  348.         nameptr = FormName;
  349.         break;
  350.          }
  351.       blk_3_info.form_name[ITEMNAMELEN] = 0;
  352.       strcpy(nameptr,blk_3_info.form_name);
  353.       /* perhaps in future add more here, check block_len for
  354.          backward compatibility */
  355.       }
  356.  
  357.    if (rangeslen) { /* free prior ranges */
  358.      farmemfree((char far *)ranges);
  359.      rangeslen = 0;
  360.    }
  361.  
  362.    if(blk_4_info.got_data == 1)
  363.       {
  364.        ranges = (int far *)blk_4_info.range_data;
  365.       rangeslen = blk_4_info.length;
  366. #ifdef XFRACTINT
  367.       fix_ranges(ranges,rangeslen,1);
  368. #endif
  369.       }
  370.  
  371.    if(blk_5_info.got_data == 1)
  372.       {
  373.       bf_math = 1;
  374.       init_bf_length(read_info.bflength);
  375.       far_memcpy((char far *)bfxmin,blk_5_info.apm_data,blk_5_info.length);
  376.       farmemfree(blk_5_info.apm_data);
  377.       }
  378.    else
  379.       bf_math = 0;
  380.    showfile = 0;           /* trigger the file load */
  381.  
  382.    return(0);
  383. }
  384.  
  385. static int find_fractal_info(char *gif_file,struct fractal_info *info,
  386.        struct ext_blk_2 *blk_2_info,struct ext_blk_3 *blk_3_info,
  387.        struct ext_blk_4 *blk_4_info,struct ext_blk_5 *blk_5_info)
  388. {
  389.    BYTE gifstart[18];
  390.    char temp1[81];
  391.    int scan_extend, block_type, block_len, data_len;
  392.    int fractinf_len;
  393.    int hdr_offset;
  394.  
  395.    blk_2_info->got_data = 0; /* initialize to no data */
  396.    blk_3_info->got_data = 0; /* initialize to no data */
  397.    blk_4_info->got_data = 0; /* initialize to no data */
  398.    blk_5_info->got_data = 0; /* initialize to no data */
  399.  
  400.    if((fp = fopen(gif_file,"rb"))==NULL)
  401.       return(-1);
  402.    fread(gifstart,18,1,fp);
  403.    if (strncmp((char *)gifstart,"GIF",3) != 0) { /* not GIF, maybe old .tga? */
  404.       if(fread(info,FRACTAL_INFO_SIZE,1,fp)==1 &&
  405.          strncmp(info->info_id,"Fractal",8)==0) {
  406.      filetype = 1; /* Targa 16 */
  407.      GET16(gifstart[O_VSIZE],fileydots);
  408.      GET16(gifstart[O_HSIZE],filexdots);
  409.      filecolors = info->colors;
  410.      fileaspectratio = screenaspect;
  411.      if(fileydots == info->ydots && filexdots == info->xdots) {
  412.         fclose(fp);
  413.         return(0);
  414.         }
  415.      }
  416.       fclose(fp);
  417.       return(-1);
  418.       }
  419.  
  420.    filetype = 0; /* GIF */
  421.    GET16(gifstart[6],filexdots);
  422.    GET16(gifstart[8],fileydots);
  423.    filecolors = 2 << (gifstart[10] & 7);
  424.    fileaspectratio = 0; /* unknown */
  425.    if (gifstart[12]) { /* calc reasonably close value from gif header */
  426.       fileaspectratio = (float)((64.0 / ((double)(gifstart[12]) + 15.0))
  427.               * (double)fileydots / (double)filexdots);
  428.       if ( fileaspectratio > screenaspect-0.03
  429.     && fileaspectratio < screenaspect+0.03)
  430.      fileaspectratio = screenaspect;
  431.       }
  432.    else
  433.       if (fileydots * 4 == filexdots * 3) /* assume the common square pixels */
  434.      fileaspectratio = screenaspect;
  435.  
  436.    /* Format of .gif extension blocks is:
  437.       1 byte    '!', extension block identifier
  438.       1 byte    extension block number, 255
  439.       1 byte    length of id, 11
  440.      11 bytes   alpha id, "fractintnnn" with fractint, nnn is secondary id
  441.        n * {
  442.       1 byte    length of block info in bytes
  443.       x bytes   block info
  444.        }
  445.       1 byte    0, extension terminator
  446.       To scan extension blocks, we first look in file at length of fractal_info
  447.       (the main extension block) from end of file, looking for a literal known
  448.       to be at start of our block info.  Then we scan forward a bit, in case
  449.       the file is from an earlier fractint vsn with shorter fractal_info.
  450.       If fractal_info is found and is from vsn>=14, it includes the total length
  451.       of all extension blocks; we then scan them all first to last to load
  452.       any optional ones which are present.
  453.       Defined extension blocks:
  454.     fractint001    header, always present
  455.     fractint002    resume info for interrupted resumable image
  456.     fractint003    additional formula type info
  457.     fractint004    ranges info
  458.     fractint005    extended precision parameters
  459.    */
  460.  
  461.    memset(info,0,FRACTAL_INFO_SIZE);
  462.    fractinf_len = FRACTAL_INFO_SIZE + (FRACTAL_INFO_SIZE+254)/255;
  463.    fseek(fp,(long)(-1-fractinf_len),SEEK_END);
  464.    fread(info,1,FRACTAL_INFO_SIZE,fp);
  465.    if (strcmp(INFO_ID,info->info_id) == 0) {
  466. #ifdef XFRACT
  467.        decode_fractal_info(info,1);
  468. #endif
  469.       hdr_offset = -1-fractinf_len;
  470.    } else {
  471.       /* didn't work 1st try, maybe an older vsn, maybe junk at eof, scan: */
  472.       int offset,i;
  473.       char tmpbuf[110];
  474.       hdr_offset = 0;
  475.       offset = 80; /* don't even check last 80 bytes of file for id */
  476.       while (offset < fractinf_len+513) { /* allow 512 garbage at eof */
  477.      offset += 100; /* go back 100 bytes at a time */
  478.      fseek(fp,(long)(0-offset),SEEK_END);
  479.      fread(tmpbuf,1,110,fp); /* read 10 extra for string compare */
  480.      for (i = 0; i < 100; ++i)
  481.         if (!strcmp(INFO_ID,&tmpbuf[i])) { /* found header? */
  482.            strcpy(info->info_id,INFO_ID);
  483.            fseek(fp,(long)(hdr_offset=i-offset),SEEK_END);
  484.            fread(info,1,FRACTAL_INFO_SIZE,fp);
  485. #ifdef XFRACT
  486.            decode_fractal_info(info,1);
  487. #endif
  488.            offset = 10000; /* force exit from outer loop */
  489.            break;
  490.            }
  491.      }
  492.       }
  493.  
  494.    if (hdr_offset) { /* we found INFO_ID */
  495.  
  496.       if (info->version >= 4) {
  497.      /* first reload main extension block, reasons:
  498.           might be over 255 chars, and thus earlier load might be bad
  499.           find exact endpoint, so scan back to start of ext blks works
  500.         */
  501.      fseek(fp,(long)(hdr_offset-15),SEEK_END);
  502.      scan_extend = 1;
  503.      while (scan_extend) {
  504.         if (fgetc(fp) != '!' /* if not what we expect just give up */
  505.           || fread(temp1,1,13,fp) != 13
  506.           || strncmp(&temp1[2],"fractint",8))
  507.            break;
  508.         temp1[13] = 0;
  509.         block_type = atoi(&temp1[10]); /* e.g. "fractint002" */
  510.         switch (block_type) {
  511.            case 1: /* "fractint001", the main extension block */
  512.           if (scan_extend == 2) { /* we've been here before, done now */
  513.              scan_extend = 0;
  514.              break;
  515.              }
  516.           load_ext_blk((char far *)info,FRACTAL_INFO_SIZE);
  517. #ifdef XFRACT
  518.           decode_fractal_info(info,1);
  519. #endif
  520.           scan_extend = 2;
  521.           /* now we know total extension len, back up to first block */
  522.           fseek(fp,0L-info->tot_extend_len,SEEK_CUR);
  523.           break;
  524.            case 2: /* resume info */
  525.           skip_ext_blk(&block_len,&data_len); /* once to get lengths */
  526.           if ((blk_2_info->resume_data = farmemalloc((long)data_len)) == NULL)
  527.              info->calc_status = 3; /* not resumable after all */
  528.           else {
  529.              fseek(fp,(long)(0-block_len),SEEK_CUR);
  530.              load_ext_blk(blk_2_info->resume_data,data_len);
  531.              blk_2_info->length = data_len;
  532.              blk_2_info->got_data = 1; /* got data */
  533.              }
  534.           break;
  535.            case 3: /* formula info */
  536.           load_ext_blk(blk_3_info->form_name,40);
  537.           blk_3_info->got_data = 1; /* got data */
  538.           /* perhaps in future add more here, check block_len for
  539.              backward compatibility */
  540.           break;
  541.            case 4: /* ranges info */
  542.           skip_ext_blk(&block_len,&data_len); /* once to get lengths */
  543.           if ((blk_4_info->range_data = (int far *)farmemalloc((long)data_len)) != NULL) {
  544.              fseek(fp,(long)(0-block_len),SEEK_CUR);
  545.              load_ext_blk((char far *)blk_4_info->range_data,data_len);
  546.              blk_4_info->length = data_len/2;
  547.              blk_4_info->got_data = 1; /* got data */
  548.              }
  549.           break;
  550.            case 5: /* extended precision parameters  */
  551.           skip_ext_blk(&block_len,&data_len); /* once to get lengths */
  552.           if ((blk_5_info->apm_data = farmemalloc((long)data_len)) != NULL) {
  553.              fseek(fp,(long)(0-block_len),SEEK_CUR);
  554.              load_ext_blk(blk_5_info->apm_data,data_len);
  555.              blk_5_info->length = data_len;
  556.              blk_5_info->got_data = 1; /* got data */
  557.              }
  558.           break;
  559.            default:
  560.           skip_ext_blk(&block_len,&data_len);
  561.            }
  562.         }
  563.      }
  564.  
  565.       fclose(fp);
  566.       fileaspectratio = screenaspect; /* if not >= v15, this is correct */
  567.       return(0);
  568.       }
  569.  
  570.    strcpy(info->info_id, "GIFFILE");
  571.    info->iterations = 150;
  572.    info->fractal_type = PLASMA;
  573.    info->xmin = -1;
  574.    info->xmax = 1;
  575.    info->ymin = -1;
  576.    info->ymax = 1;
  577.    info->x3rd = -1;
  578.    info->y3rd = -1;
  579.    info->creal = 0;
  580.    info->cimag = 0;
  581.    info->videomodeax=255;
  582.    info->videomodebx=255;
  583.    info->videomodecx=255;
  584.    info->videomodedx=255;
  585.    info->dotmode = 0;
  586.    info->xdots = (short)filexdots;
  587.    info->ydots = (short)fileydots;
  588.    info->colors = (short)filecolors;
  589.    info->version = 0; /* this forces lots more init at calling end too */
  590.  
  591.    /* zero means we won */
  592.    fclose(fp);
  593.    return(0);
  594. }
  595.  
  596. static void load_ext_blk(char far *loadptr,int loadlen)
  597. {
  598.    int len;
  599.    while ((len = fgetc(fp)) > 0) {
  600.       while (--len >= 0) {
  601.      if (--loadlen >= 0)
  602.         *(loadptr++) = (char)fgetc(fp);
  603.      else
  604.         fgetc(fp); /* discard excess characters */
  605.      }
  606.       }
  607. }
  608.  
  609. static void skip_ext_blk(int *block_len, int *data_len)
  610. {
  611.    int len;
  612.    *data_len = 0;
  613.    *block_len = 1;
  614.    while ((len = fgetc(fp)) > 0) {
  615.       fseek(fp,(long)len,SEEK_CUR);
  616.       *data_len += len;
  617.       *block_len += len + 1;
  618.       }
  619. }
  620.  
  621.  
  622. /* switch obsolete fractal types to new generalizations */
  623. static void backwardscompat(struct fractal_info *info)
  624. {
  625.    switch(fractype) {
  626.       case LAMBDASINE:
  627.      fractype = LAMBDATRIGFP;
  628.      trigndx[0] = SIN;
  629.      break;
  630.       case LAMBDACOS    :
  631.      fractype = LAMBDATRIGFP;
  632.      trigndx[0] = COS;
  633.      break;
  634.       case LAMBDAEXP    :
  635.      fractype = LAMBDATRIGFP;
  636.      trigndx[0] = EXP;
  637.      break;
  638.       case MANDELSINE    :
  639.      fractype = MANDELTRIGFP;
  640.      trigndx[0] = SIN;
  641.      break;
  642.       case MANDELCOS    :
  643.      fractype = MANDELTRIGFP;
  644.      trigndx[0] = COS;
  645.      break;
  646.       case MANDELEXP    :
  647.      fractype = MANDELTRIGFP;
  648.      trigndx[0] = EXP;
  649.      break;
  650.       case MANDELSINH    :
  651.      fractype = MANDELTRIGFP;
  652.      trigndx[0] = SINH;
  653.      break;
  654.       case LAMBDASINH    :
  655.      fractype = LAMBDATRIGFP;
  656.      trigndx[0] = SINH;
  657.      break;
  658.       case MANDELCOSH    :
  659.      fractype = MANDELTRIGFP;
  660.      trigndx[0] = COSH;
  661.      break;
  662.       case LAMBDACOSH    :
  663.      fractype = LAMBDATRIGFP;
  664.      trigndx[0] = COSH;
  665.      break;
  666.       case LMANDELSINE    :
  667.      fractype = MANDELTRIG;
  668.      trigndx[0] = SIN;
  669.      break;
  670.       case LLAMBDASINE    :
  671.      fractype = LAMBDATRIG;
  672.      trigndx[0] = SIN;
  673.      break;
  674.       case LMANDELCOS    :
  675.      fractype = MANDELTRIG;
  676.      trigndx[0] = COS;
  677.      break;
  678.       case LLAMBDACOS    :
  679.      fractype = LAMBDATRIG;
  680.      trigndx[0] = COS;
  681.      break;
  682.       case LMANDELSINH    :
  683.      fractype = MANDELTRIG;
  684.      trigndx[0] = SINH;
  685.      break;
  686.       case LLAMBDASINH    :
  687.      fractype = LAMBDATRIG;
  688.      trigndx[0] = SINH;
  689.      break;
  690.       case LMANDELCOSH    :
  691.      fractype = MANDELTRIG;
  692.      trigndx[0] = COSH;
  693.      break;
  694.       case LLAMBDACOSH    :
  695.      fractype = LAMBDATRIG;
  696.      trigndx[0] = COSH;
  697.      break;
  698.       case LMANDELEXP    :
  699.      fractype = MANDELTRIG;
  700.      trigndx[0] = EXP;
  701.      break;
  702.       case LLAMBDAEXP    :
  703.      fractype = LAMBDATRIG;
  704.      trigndx[0] = EXP;
  705.      break;
  706.       case DEMM     :
  707.      fractype = MANDELFP;
  708.      usr_distest = (info->ydots - 1) * 2;
  709.      break;
  710.       case DEMJ     :
  711.      fractype = JULIAFP;
  712.      usr_distest = (info->ydots - 1) * 2;
  713.      break;
  714.       case MANDELLAMBDA :
  715.      useinitorbit = 2;
  716.      break;
  717.       }
  718.    curfractalspecific = &fractalspecific[fractype];
  719. }
  720.  
  721. /* switch old bifurcation fractal types to new generalizations */
  722. void set_if_old_bif(void)
  723. {
  724. /* set functions if not set already, may need to check 'functionpreloaded'
  725.    before calling this routine.  JCO 7/5/92 */
  726.  
  727.    switch(fractype) {
  728.       case BIFURCATION:
  729.       case LBIFURCATION:
  730.       case BIFSTEWART:
  731.       case LBIFSTEWART:
  732.       case BIFLAMBDA:
  733.       case LBIFLAMBDA:
  734.         set_trig_array(0,"ident");
  735.         break;
  736.  
  737.       case BIFEQSINPI:
  738.       case LBIFEQSINPI:
  739.       case BIFADSINPI:
  740.       case LBIFADSINPI:
  741.         set_trig_array(0,s_sin);
  742.         break;
  743.    }
  744. }
  745.  
  746. void backwards_v18(void)
  747. {
  748.   if(!functionpreloaded)
  749.     set_if_old_bif(); /* old bifs need function set, JCO 7/5/92 */
  750.   if(fractype==MANDELTRIG && usr_floatflag==1
  751.      && save_release < 1800 && bailout == 0)
  752.     bailout = 2500;
  753.   if(fractype==LAMBDATRIG && usr_floatflag==1
  754.      && save_release < 1800 && bailout == 0)
  755.     bailout = 2500;
  756. }
  757.  
  758. void backwards_v19(void)
  759. {
  760.   if(fractype==MARKSJULIA && save_release < 1825)
  761.     if(param[2] == 0)
  762.        param[2] = 2;
  763.     else
  764.        param[2] += 1;
  765.   if(fractype==MARKSJULIAFP && save_release < 1825)
  766.     if(param[2] == 0)
  767.        param[2] = 2;
  768.     else
  769.        param[2] += 1;
  770.   if((fractype==FORMULA || fractype==FFORMULA) && save_release < 1824)
  771.     inversion[0] = inversion[1] = inversion[2] = invert = 0;
  772.   if(fix_bof())
  773.     no_mag_calc = 1; /* fractal has old bof60/61 problem with magnitude */
  774.   else
  775.     no_mag_calc = 0;
  776.   if(fix_period_bof())
  777.     use_old_period = 1; /* fractal uses old periodicity method */
  778.   else
  779.     use_old_period = 0;
  780.   if(save_release < 1827 && distest)
  781.     use_old_distest = 1; /* use old distest code */
  782.   else
  783.     use_old_distest = 0; /* use new distest code */
  784. }
  785.  
  786. int fix_bof(void)
  787. {
  788. int ret = 0;
  789.  if (inside <= BOF60 && inside >= BOF61 && save_release < 1826)
  790.     if ((curfractalspecific->calctype == StandardFractal &&
  791.         (curfractalspecific->flags & BAILTEST) == 0) ||
  792.         (fractype==FORMULA || fractype==FFORMULA))
  793.         ret = 1;
  794. return (ret);
  795. }
  796.  
  797. int fix_period_bof(void)
  798. {
  799. int ret = 0;
  800.  if (inside <= BOF60 && inside >= BOF61 && save_release < 1826)
  801.     ret = 1;
  802. return (ret);
  803. }
  804.  
  805. /* browse code RB*/
  806.  
  807. #define MAX_WINDOWS_OPEN 450
  808. #define BROWSE_DATA 32768l
  809. /* 450 * sizeof(window) must be < (65535 - BROWSE_DATA) = 32767 */
  810. /* 450 * 67 = 30150 */
  811.  
  812.   struct window {
  813.      double xmin;       /* for fgetwindow on screen browser */
  814.      double xmax;
  815.      double ymin;
  816.      double ymax;
  817.      double x3rd;
  818.      double y3rd;
  819.      char name[13];/* for filename */
  820.      int boxcount;
  821.      int far *savebox; /* for coordinates and colors of box */
  822.      };
  823.  
  824. /* prototypes */
  825. static void drawindow(int, struct window far *);
  826. static char is_visible_window( struct fractal_info * );
  827. static void transform( struct dblcoords * );
  828. static char paramsOK( struct fractal_info * );
  829. static char typeOK( struct fractal_info *, struct ext_blk_3 * );
  830. static char functionOK( struct fractal_info *, int );
  831.  
  832. char browsename[13]; /* name for browse file */
  833.  
  834. /* fgetwindow reads all .GIF files and draws window outlines on the screen */
  835. int fgetwindow(void)
  836.   {
  837.     struct fractal_info read_info;
  838.     struct ext_blk_2 blk_2_info;
  839.     struct ext_blk_3 blk_3_info;
  840.     struct ext_blk_4 blk_4_info;
  841.     struct ext_blk_5 blk_5_info;
  842.     time_t thistime,lastime;
  843.     char mesg[40],newname[60];
  844.     int c,i,index,done,wincount,toggle;
  845.     struct window far *winlist; /* that _should_ do! */
  846.     char drive[FILE_MAX_DRIVE];
  847.     char dir[FILE_MAX_DIR];
  848.     char fname[FILE_MAX_FNAME];
  849.     char ext[FILE_MAX_EXT];
  850.     char tmpmask[FILE_MAX_PATH];
  851.     int no_memory_left = 0;
  852.     int far *save_some_mem;
  853.  
  854.      /* steal an array */
  855.      winlist = (struct window far *)MK_FP(extraseg,BROWSE_DATA);
  856.      rescan:  /* entry for changed browse parms */
  857.      find_special_colors();
  858.      time(&lastime);
  859.      toggle = 0;
  860.      wincount = 0;
  861.      no_sub_images = FALSE;
  862.      splitpath(readname,drive,dir,NULL,NULL);
  863.      splitpath(browsemask,NULL,NULL,fname,ext);
  864.      makepath(tmpmask,drive,dir,fname,ext);
  865.      if ((save_some_mem = farmemalloc(10240))==NULL) /* steal 10K! */
  866.         no_memory_left = 1; /* to display message, else OOL */
  867.      done=fr_findfirst(tmpmask);
  868.                    /* draw all visible windows */
  869.      while (!done)
  870.      {
  871.        if(keypressed())
  872.        {
  873.           getakey();
  874.           break;
  875.        }   
  876.        splitpath(DTA.filename,NULL,NULL,fname,ext);
  877.        makepath(tmpmask,drive,dir,fname,ext);
  878.        if( !find_fractal_info(tmpmask,&read_info,&blk_2_info,
  879.                               &blk_3_info,&blk_4_info,&blk_5_info) &&
  880.        (typeOK(&read_info,&blk_3_info) || !brwschecktype) &&
  881.        (paramsOK(&read_info) || !brwscheckparms) &&
  882.        stricmp(browsename,DTA.filename) &&
  883.        blk_5_info.got_data != 1 &&
  884.        is_visible_window(&read_info)
  885.      )
  886.      {
  887.        winlist[wincount].xmin = read_info.xmin ;
  888.        winlist[wincount].xmax = read_info.xmax ;
  889.        winlist[wincount].ymin = read_info.ymin ;
  890.        winlist[wincount].ymax = read_info.ymax ;
  891.        winlist[wincount].x3rd = read_info.x3rd ;
  892.        winlist[wincount].y3rd = read_info.y3rd ;
  893.        far_strcpy(winlist[wincount].name,DTA.filename);
  894.        drawindow(color_medium,&winlist[wincount]);
  895.        boxcount <<= 1; /*boxcount*2;*/ /* double for byte count */
  896.        winlist[wincount].boxcount = boxcount;
  897.        if ((winlist[wincount].savebox = farmemalloc(6*boxcount))==NULL){
  898.           boxcount >>= 1; /* can't allocate any more */
  899.           clearbox(); /* clean up the mess */
  900.           no_memory_left = 1;
  901.        }
  902.        else {
  903.           far_memcpy(winlist[wincount].savebox,boxx,boxcount);
  904.           far_memcpy(winlist[wincount].savebox+boxcount,boxy,boxcount);
  905.           far_memcpy(winlist[wincount].savebox+boxcount*2,boxvalues,boxcount);
  906.           wincount++;
  907.        }
  908.      }
  909.  
  910.     if(blk_2_info.got_data == 1) /* Clean up any far memory allocated */
  911.        farmemfree(blk_2_info.resume_data);
  912.     if(blk_4_info.got_data == 1) /* Clean up any far memory allocated */
  913.        farmemfree(blk_4_info.range_data);
  914.     if(blk_5_info.got_data == 1) /* Clean up any far memory allocated */
  915.        farmemfree(blk_5_info.apm_data);
  916.  
  917.     done=(fr_findnext() || wincount >= MAX_WINDOWS_OPEN || no_memory_left);
  918.       }
  919.       farmemfree(save_some_mem); /* release memory for messages, yuk! */
  920.       if (no_memory_left)
  921.       {
  922.          static FCODE msg[] = {"sorry...out of memory, can't show more"};
  923.        texttempmsg(msg);/* doesn't work if NO far memory available, go figure */
  924.       }
  925.       if (wincount >= MAX_WINDOWS_OPEN)
  926.       {
  927.          static FCODE msg[] = {"sorry...no more space, can't show more"};
  928.        texttempmsg(msg);
  929.       }
  930.  c=0;
  931.  if (wincount)
  932.  {
  933.       buzzer(0); /*let user know we've finished */
  934.       index=0;done = 0;
  935.       showtempmsg(winlist[index].name);
  936.       while ( !done)  /* on exit done = 1 for quick exit,
  937.                  done = 2 for erase boxes and  exit
  938.                  done = 3 for rescan
  939.                  done = 4 for set boxes and exit to save image */
  940.       {
  941.     while (!keypressed())
  942.     {
  943.       time(&thistime);
  944.       if (difftime(thistime,lastime) > .2 ) {
  945.       lastime=thistime;
  946.       toggle = 1- toggle;
  947.       }
  948.       if (toggle)
  949.         drawindow(color_bright,&winlist[index]);   /* flash current window */
  950.       else
  951.         drawindow(color_dark,&winlist[index]);
  952.     }
  953.  
  954.       c=getakey();
  955.       switch (c) {
  956.      case RIGHT_ARROW:
  957.      case LEFT_ARROW:
  958.      case DOWN_ARROW:
  959.      case UP_ARROW:
  960.        cleartempmsg();
  961.        drawindow(color_medium,&winlist[index]);/* dim last window */
  962.        if (c==RIGHT_ARROW || c== UP_ARROW) {
  963.          do {
  964.           index++;                     /* shift attention to next window */
  965.           if (index >= wincount) index=0;
  966.          }while(winlist[index].boxcount < 0 );
  967.        }
  968.        else {
  969.         do {
  970.          index -- ;
  971.          if ( index <0 )  index = wincount -1 ;
  972.         }while (winlist[index].boxcount < 0 );
  973.        }
  974.        showtempmsg(winlist[index].name);
  975.        break;
  976.  
  977.     case ENTER:
  978.     case ENTER_2:   /* this file please */
  979.       far_strcpy(browsename,winlist[index].name);
  980.       done = 1;
  981.     break;
  982.  
  983.     case ESC:
  984.     case 'l':
  985.     case 'L':
  986.       autobrowse = FALSE;
  987.       done = 2;
  988.       break;
  989.  
  990.     case 'D': /* delete file */
  991.       cleartempmsg();
  992.       strcpy(mesg,"");
  993.       strcat(mesg,"Delete ");
  994.       far_strcat(mesg,winlist[index].name);
  995.       strcat(mesg,"? (Y/N)");
  996.       showtempmsg(mesg);
  997.       while (!keypressed()) ;
  998.       cleartempmsg();
  999.       c = getakey();
  1000.       if ( c == 'Y' && doublecaution ) {
  1001.        static FCODE msg[] = {"ARE YOU SURE???? (Y/N)"};
  1002.        texttempmsg(msg);
  1003.         if ( getakey() != 'Y') c = 'N';
  1004.       }
  1005.       if ( c == 'Y' ) {
  1006.       splitpath(readname,drive,dir,NULL,NULL);
  1007.       splitpath(winlist[index].name,NULL,NULL,fname,ext);
  1008.       makepath(tmpmask,drive,dir,fname,ext);
  1009.       if ( !unlink(tmpmask)) {
  1010.         /* erase box */
  1011.         boxcount = winlist[index].boxcount;
  1012.         far_memcpy(boxx,winlist[index].savebox,boxcount);
  1013.         far_memcpy(boxy,winlist[index].savebox+boxcount,boxcount);
  1014.         far_memcpy(boxvalues,winlist[index].savebox+boxcount*2,boxcount);
  1015.         boxcount >>= 1;
  1016.         clearbox();
  1017.         winlist[index].boxcount = -1;
  1018.         if (wincount == 1){
  1019.            done = 1;
  1020.            break;
  1021.         }
  1022.         index++;
  1023.         if (index >= wincount) index = 0;
  1024.         showtempmsg(winlist[index].name);
  1025.         break;
  1026.         }
  1027.       else if( errno == EACCES ) {
  1028.           static FCODE msg[] = {"Sorry...it's a read only file, can't del"};
  1029.           texttempmsg(msg);
  1030.           showtempmsg(winlist[index].name);
  1031.           break;
  1032.           }
  1033.       }
  1034.           {
  1035.       static FCODE msg[] = {"file not deleted (phew!)"};
  1036.       texttempmsg(msg);
  1037.       }
  1038.       showtempmsg(winlist[index].name);
  1039.       break;
  1040.  
  1041.     case 'R':
  1042.      cleartempmsg();
  1043.      stackscreen();
  1044.      newname[0] = 0;
  1045.      strcpy(mesg,"");
  1046.      {
  1047.      static FCODE msg[] = {"Enter the new filename for "};
  1048.      far_strcat((char far *)mesg,msg);
  1049.      }
  1050.      splitpath(readname,drive,dir,NULL,NULL);
  1051.      splitpath(winlist[index].name,NULL,NULL,fname,ext);
  1052.      makepath(tmpmask,drive,dir,fname,ext);
  1053.      strcpy(newname,tmpmask);
  1054.      strcat(mesg,tmpmask);
  1055.      i = field_prompt(0,mesg,NULL,newname,60,NULL);
  1056.      unstackscreen();
  1057.      if( i != -1)
  1058.       if (!rename(tmpmask,newname))
  1059.         if (errno == EACCES)
  1060.         {
  1061.            static FCODE msg[] = {"sorry....can't rename"};
  1062.         texttempmsg(msg);
  1063.             }
  1064.       else {
  1065.        splitpath(newname,NULL,NULL,fname,ext);
  1066.        makepath(tmpmask,NULL,NULL,fname,ext);
  1067.        far_strcpy(winlist[index].name,tmpmask);
  1068.        }
  1069.      showtempmsg(winlist[index].name);
  1070.      break;
  1071.  
  1072.     case 2: /* ctrl B */
  1073.       cleartempmsg();
  1074.       stackscreen();
  1075.       done = abs(get_browse_params());
  1076.       unstackscreen();
  1077.       showtempmsg(winlist[index].name);
  1078.       break;
  1079.  
  1080.     case 's': /* save image with boxes */
  1081.       autobrowse = FALSE;
  1082.       drawindow(color_medium,&winlist[index]); /* current window white */
  1083.       done = 4;
  1084.       break;
  1085.  
  1086.     case '\\': /*back out to last image */
  1087.       done = 2;
  1088.       break;
  1089.  
  1090.     default:
  1091.       break;
  1092.      } /*switch */
  1093.     } /*while*/
  1094.  
  1095.     /* now clean up memory (and the screen if necessary) */
  1096.     cleartempmsg();
  1097.     for (index=wincount-1;index>=0;index--){ /* don't need index, reuse it */
  1098.        if (done > 1 && done < 4 && (winlist[index].boxcount > 0)) {
  1099.       boxcount = winlist[index].boxcount;
  1100.       far_memcpy(boxx,winlist[index].savebox,boxcount);
  1101.       far_memcpy(boxy,winlist[index].savebox+boxcount,boxcount);
  1102.       far_memcpy(boxvalues,winlist[index].savebox+boxcount*2,boxcount);
  1103.       boxcount >>= 1;
  1104.       clearbox();
  1105.        }
  1106.        farmemfree(winlist[index].savebox);
  1107.     }
  1108.     if (done == 3) goto rescan; /* hey everybody I just used the g word! */
  1109.  
  1110.  }/*if*/
  1111.  else {
  1112.    static FCODE msg[] = {"sorry.. I can't find anything"};
  1113.    buzzer(1); /*no suitable files in directory! */
  1114.    texttempmsg(msg);
  1115.    no_sub_images = TRUE;
  1116.  }
  1117. return(c);
  1118. }
  1119.  
  1120. static void drawindow(int colour,struct window far *info)
  1121. {
  1122.    int cross_size;
  1123.    unsigned int temp;
  1124.    struct dblcoords tl,bl,tr,br;
  1125.    struct coords itl,ibl,itr,ibr;
  1126.    tl.x=info->xmin;
  1127.    tl.y=info->ymax;
  1128.    tr.x=(info->xmax)-(info->x3rd-info->xmin);
  1129.    tr.y=(info->ymax)+(info->ymin-info->y3rd);
  1130.    bl.x=info->x3rd;
  1131.    bl.y=info->y3rd;
  1132.    br.x=info->xmax;
  1133.    br.y=info->ymin;
  1134.    /* tranform maps real plane co-ords onto the current screen view
  1135.      see below */
  1136.    transform(&tl);itl.x=(int)tl.x;itl.y=(int)tl.y;
  1137.    transform(&tr);itr.x=(int)tr.x;itr.y=(int)tr.y;
  1138.    transform(&bl);ibl.x=(int)bl.x;ibl.y=(int)bl.y;
  1139.    transform(&br);ibr.x=(int)br.x;ibr.y=(int)br.y;
  1140.    boxcolor=colour;
  1141.    boxcount = 0;
  1142.    temp = (unsigned int)sqrt(sqr(br.x - tl.x) + sqr(tl.y - br.y));
  1143.     if (temp >= (unsigned int)minbox) {
  1144.     /* big enough on screen to show up as a box so draw it */
  1145.     /* corner pixels */
  1146.      addbox(itl);
  1147.      addbox(itr);
  1148.      addbox(ibl);
  1149.      addbox(ibr);
  1150.      drawlines(itl,itr,ibl.x-itl.x,ibl.y-itl.y); /* top & bottom lines */
  1151.      drawlines(itl,ibl,itr.x-itl.x,itr.y-itl.y); /* left & right lines */
  1152.      dispbox();
  1153.     }
  1154.     else { /* draw crosshairs */
  1155.     cross_size = ydots / 45;
  1156.     itr.x = itl.x - cross_size;
  1157.     itr.y = itl.y;
  1158.     ibl.y = itl.y - cross_size;
  1159.     ibl.x = itl.x;
  1160.     drawlines(itl,itr,ibl.x-itr.x,0); /* top & bottom lines */
  1161.     drawlines(itl,ibl,0,itr.y-ibl.y); /* left & right lines */
  1162.     dispbox();
  1163.    }
  1164. }
  1165.  
  1166. static void transform(struct dblcoords *point)
  1167. { /* maps points onto view screen*/
  1168.   double theta1,theta2,theta3,scalex,scaley,hypot;
  1169.  
  1170. /* sqr() defined in fractint.h */
  1171.  
  1172.   scaley=ydots/(sqrt(sqr(xx3rd-xxmin)+sqr(yymax-yy3rd)));
  1173.   scalex=xdots/(sqrt(sqr(xxmax-xx3rd)+sqr(yymin-yy3rd)));
  1174.  
  1175.   theta1=atan2(point->x-xx3rd,point->y-yy3rd);
  1176.   theta2=atan2(xxmax-xx3rd,yymin-yy3rd);
  1177.   theta3=theta2-theta1; /* calculate angle of point from corner of screen */
  1178.  
  1179.   hypot=sqrt(sqr(point->x-xx3rd)+sqr(point->y-yy3rd));
  1180.  
  1181.   point->x=hypot*cos(theta3)*scalex;
  1182.   point->y=ydots-(hypot*sin(theta3)*scaley);
  1183.  
  1184.  
  1185.    }
  1186.  
  1187. static char is_visible_window( struct fractal_info *info )
  1188. {
  1189.  struct dblcoords tl,tr,bl,br;
  1190.  int cornercount;
  1191.  double toobig;
  1192.  toobig = sqrt(sqr((double)sxdots)+sqr((double)sydots)) * 1.5;
  1193.   /* arbitrary value... stops browser zooming out too far */
  1194.  cornercount=0;
  1195.  tl.x=info->xmin;
  1196.  tl.y=info->ymax;
  1197.  tr.x=(info->xmax)-(info->x3rd-info->xmin);
  1198.  tr.y=(info->ymax)+(info->ymin-info->y3rd);
  1199.  bl.x=info->x3rd;
  1200.  bl.y=info->y3rd;
  1201.  br.x=info->xmax;
  1202.  br.y=info->ymin;
  1203.  
  1204.  transform(&tl);
  1205.  transform(&bl);  /* transform the corners to screen space */
  1206.  transform(&tr);
  1207.  transform(&br);
  1208.    if (sqrt(sqr(tr.x-bl.x)+sqr(tr.y-bl.y)) < toosmall ) return(FALSE);
  1209.  /* reject anything too small onscreen */
  1210.    if (sqrt(sqr(tr.x-bl.x)+sqr(tr.y-bl.y)) > toobig   ) return(FALSE);
  1211.  /* or too big... */
  1212.  /* now see how many corners are on the screen, accept if one or more */
  1213.  if ( tl.x >=0 && tl.x <= xdots && tl.y >=0 && tl.y <= ydots ) cornercount ++;
  1214.  if ( bl.x >=0 && bl.x <= xdots && bl.y >=0 && bl.y <= ydots ) cornercount ++;
  1215.  if ( tr.x >=0 && tr.x <= xdots && tr.y >=0 && tr.y <= ydots ) cornercount ++;
  1216.  if ( br.x >=0 && br.x <= xdots && br.y >=0 && br.y <= ydots ) cornercount ++;
  1217.  
  1218.  if (cornercount >=1 ) return( TRUE );
  1219.     else return( FALSE );
  1220.  }
  1221.  
  1222. static char paramsOK( struct fractal_info *info )
  1223. {
  1224. double tmpparm3, tmpparm4;
  1225. #define MINDIF 0.001
  1226.  
  1227.    if( info->version > 6) {
  1228.      tmpparm3 = info->dparm3;
  1229.      tmpparm4 = info->dparm4;
  1230.    }
  1231.    else{
  1232.      tmpparm3 = info->parm3;
  1233.      roundfloatd(&tmpparm3);
  1234.      tmpparm4 = info->parm4;
  1235.      roundfloatd(&tmpparm4);
  1236.    }
  1237.    if( fabs(info->creal - param[0]) < MINDIF &&
  1238.        fabs(info->cimag - param[1]) < MINDIF &&
  1239.        fabs(tmpparm3 - param[2]) < MINDIF &&
  1240.        fabs(tmpparm4 - param[3]) < MINDIF &&
  1241.        info->invert[0] - inversion[0] < MINDIF)
  1242.       return(1); /* parameters are in range */
  1243.    else
  1244.       return(0);
  1245. }
  1246.  
  1247. static char functionOK( struct fractal_info *info, int numfn)
  1248. {
  1249.  int i, mzmatch;
  1250.    mzmatch = 0;
  1251.    for(i=0; i<numfn; i++){
  1252.      if( info->trigndx[i] != trigndx[i] )
  1253.     mzmatch++;
  1254.    }
  1255.    if(mzmatch > 0)
  1256.      return(0);
  1257.    else
  1258.      return(1); /* they all match */
  1259. }
  1260.  
  1261. static char typeOK( struct fractal_info *info, struct ext_blk_3 *blk_3_info )
  1262. {
  1263.  int numfn;
  1264.    if( (fractype == FORMULA || fractype == FFORMULA) &&
  1265.      (info->fractal_type == FORMULA || info->fractal_type == FFORMULA) )
  1266.    {
  1267.        if( !stricmp(blk_3_info->form_name,FormName) )
  1268.        {
  1269.      numfn = maxfn;
  1270.      if (numfn>0)
  1271.        return(functionOK(info, numfn));
  1272.      else
  1273.        return(1); /* match up formula names with no functions */
  1274.        }
  1275.        else
  1276.      return(0); /* two formulas but names don't match */
  1277.    }
  1278.    else if(info->fractal_type == fractype ||
  1279.            info->fractal_type == curfractalspecific->tofloat)
  1280.    {
  1281.      numfn = (curfractalspecific->flags >> 6) & 7;
  1282.      if (numfn>0)
  1283.        return(functionOK(info, numfn));
  1284.      else
  1285.        return(1); /* match types with no functions */
  1286.    }
  1287.    else
  1288.        return(0); /* no match */
  1289. }
  1290.